#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libdwarf.h>
#include <dwarf.h>

// 递归遍历DIE树查找变量地址信息
void traverse_die_for_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half address_size, const char* target_var) {
    Dwarf_Error error;
    Dwarf_Die child_die;
    Dwarf_Half tag;
    
    if (dwarf_tag(die, &tag, &error) != DW_DLV_OK) {
        return;
    }
    
    // 检查是否是变量
    if (tag == DW_TAG_variable) {
        char* name = NULL;
        if (dwarf_diename(die, &name, &error) == DW_DLV_OK && name != NULL) {
            // 获取位置信息
            Dwarf_Attribute loc_attr;
            if (dwarf_attr(die, DW_AT_location, &loc_attr, &error) == DW_DLV_OK) {
                Dwarf_Block* block;
                if (dwarf_formblock(loc_attr, &block, &error) == DW_DLV_OK) {
                    // 检查是否是DW_OP_addr操作码
                    if (block->bl_len > 0) {
                        unsigned char* data = (unsigned char*)block->bl_data;
                        
                        // DW_OP_addr操作码是0x03
                        if (data[0] == DW_OP_addr && block->bl_len >= 1 + address_size) {
                            // 提取地址
                            Dwarf_Addr addr = 0;
                            memcpy(&addr, data + 1, address_size);
                            
                            // 如果指定了目标变量名，只显示匹配的变量
                            if (target_var == NULL || strcmp(name, target_var) == 0) {
                                printf("变量: %s\n", name);
                                printf("  DW_OP_addr地址: 0x%016llx\n", (unsigned long long)addr);
                                printf("  操作码: 0x%02x (DW_OP_addr)\n", DW_OP_addr);
                                printf("  位置信息块大小: %llu bytes\n", (unsigned long long)block->bl_len);
                                printf("  完整位置信息: ");
                                for (Dwarf_Unsigned i = 0; i < block->bl_len; i++) {
                                    printf("%02x ", data[i]);
                                }
                                printf("\n\n");
                                
                                // 如果找到了目标变量，可以提前返回
                                if (target_var != NULL) {
                                    dwarf_dealloc(dbg, block, DW_DLA_BLOCK);
                                    dwarf_dealloc(dbg, loc_attr, DW_DLA_ATTR);
                                    dwarf_dealloc(dbg, name, DW_DLA_STRING);
                                    return;
                                }
                            }
                        }
                    }
                    
                    dwarf_dealloc(dbg, block, DW_DLA_BLOCK);
                }
                dwarf_dealloc(dbg, loc_attr, DW_DLA_ATTR);
            }
            dwarf_dealloc(dbg, name, DW_DLA_STRING);
        }
    }
    
    // 递归遍历子DIE
    if (dwarf_child(die, &child_die, &error) == DW_DLV_OK) {
        traverse_die_for_addr(dbg, child_die, address_size, target_var);
        dwarf_dealloc(dbg, child_die, DW_DLA_DIE);
    }
    
    // 遍历兄弟DIE
    Dwarf_Die sibling_die;
    if (dwarf_siblingof_b(dbg, die, 1, &sibling_die, &error) == DW_DLV_OK) {
        traverse_die_for_addr(dbg, sibling_die, address_size, target_var);
        dwarf_dealloc(dbg, sibling_die, DW_DLA_DIE);
    }
}

// 根据变量名查找DW_OP_addr地址
Dwarf_Addr find_var_addr_by_name(Dwarf_Debug dbg, const char* var_name) {
    Dwarf_Error error;
    Dwarf_Unsigned cu_header_length;
    Dwarf_Half version_stamp;
    Dwarf_Off abbrev_offset;
    Dwarf_Half address_size;
    Dwarf_Half length_size;
    Dwarf_Half extension_size;
    Dwarf_Sig8 type_signature;
    Dwarf_Unsigned typeoffset;
    Dwarf_Unsigned next_cu_header;
    Dwarf_Die cu_die;
    Dwarf_Half header_cu_type;
    
    Dwarf_Addr found_addr = 0;
    int found = 0;
    
    // 遍历所有编译单元
    while (dwarf_next_cu_header_d(dbg, 1, &cu_header_length, &version_stamp, 
                                 &abbrev_offset, &address_size, &length_size, 
                                 &extension_size, &type_signature, &typeoffset, 
                                 &next_cu_header, &header_cu_type, &error) == DW_DLV_OK) {
        
        if (dwarf_siblingof_b(dbg, NULL, 1, &cu_die, &error) != DW_DLV_OK) {
            continue;
        }
        
        // 递归遍历DIE树查找特定变量
        Dwarf_Die child_die;
        if (dwarf_child(cu_die, &child_die, &error) == DW_DLV_OK) {
            // 使用辅助函数来查找变量
            traverse_die_for_addr(dbg, child_die, address_size, var_name);
            dwarf_dealloc(dbg, child_die, DW_DLA_DIE);
        }
        
        dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
    }
    
    return found_addr;
}

// 解析ELF文件的DWARF信息
void parse_dwarf_addr_from_elf(const char* filename, const char* target_var) {
    Dwarf_Debug dbg = 0;
    int res;
    Dwarf_Error error;
    
    if (target_var == NULL) {
        printf("=== DW_OP_addr地址信息解析 (ELF文件) ===\n");
    } else {
        printf("=== 查找变量 '%s' 的DW_OP_addr地址 ===\n", target_var);
    }
    printf("文件: %s\n\n", filename);
    
    // 打开DWARF调试信息
    res = dwarf_init_path(filename, NULL, 0, 0, NULL, NULL, &dbg, &error);
    if (res != DW_DLV_OK) {
        printf("无法打开DWARF调试信息\n");
        return;
    }
    
    Dwarf_Unsigned cu_header_length;
    Dwarf_Half version_stamp;
    Dwarf_Off abbrev_offset;
    Dwarf_Half address_size;
    Dwarf_Half length_size;
    Dwarf_Half extension_size;
    Dwarf_Sig8 type_signature;
    Dwarf_Unsigned typeoffset;
    Dwarf_Unsigned next_cu_header;
    Dwarf_Die cu_die;
    
    // 遍历所有编译单元
    Dwarf_Half header_cu_type;
    while (dwarf_next_cu_header_d(dbg, 1, &cu_header_length, &version_stamp, 
                                 &abbrev_offset, &address_size, &length_size, 
                                 &extension_size, &type_signature, &typeoffset, 
                                 &next_cu_header, &header_cu_type, &error) == DW_DLV_OK) {
        
        if (dwarf_siblingof_b(dbg, NULL, 1, &cu_die, &error) != DW_DLV_OK) {
            continue;
        }
        
        if (target_var == NULL) {
            printf("编译单元版本: %d, 地址大小: %d bytes\n", version_stamp, address_size);
        }
        
        // 递归遍历DIE树查找变量
        Dwarf_Die child_die;
        if (dwarf_child(cu_die, &child_die, &error) == DW_DLV_OK) {
            traverse_die_for_addr(dbg, child_die, address_size, target_var);
            dwarf_dealloc(dbg, child_die, DW_DLA_DIE);
        }
        
        dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
    }
    
    dwarf_finish(dbg);
}

int main(int argc, char* argv[]) {
    if (argc < 2 || argc > 3) {
        printf("用法: %s <可执行文件> [变量名]\n", argv[0]);
        printf("示例: %s test_variable_types\n", argv[0]);
        printf("示例: %s test_variable_types global_array_var\n", argv[0]);
        return 1;
    }
    
    const char* target_var = NULL;
    if (argc == 3) {
        target_var = argv[2];
    }
    
    parse_dwarf_addr_from_elf(argv[1], target_var);
    return 0;
}